package edu.uidaho.RG;

import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

import android.app.Activity;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import android.widget.ToggleButton;
//import android.widget.ToggleButton;

//import com.android.future.usb.UsbAccessory;
//import com.android.future.usb.UsbManager;
//Trying this change to work for xformer tablet
import android.hardware.usb.UsbAccessory;
import android.hardware.usb.UsbManager;

public class RectGameActivity extends Activity implements Runnable{
 
	private static final String TAG = "ArduinoAccessory";
	public TextView mResponseField;
	private int readIn1;  //This is the variable reading from Arduino pot
	private int readIn2;
	private int readIn3;
	private int readIn4;
	private static final String ACTION_USB_PERMISSION = "com.google.android.DemoKit.action.USB_PERMISSION";
	private UsbManager mUsbManager;
	private PendingIntent mPermissionIntent;
	private boolean mPermissionRequestPending;
	private UsbAccessory mAccessory;
	private ParcelFileDescriptor mFileDescriptor;
	private FileInputStream mInputStream;
	private FileOutputStream mOutputStream;
	//private ToggleButton buttonLED;
	private ToggleButton USBReset;
	
	/** Called when the activity is first created. */
	@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
		mResponseField = (TextView)findViewById(R.id.arduinoresponse);
		//buttonLED = (ToggleButton) findViewById(R.id.toggleButton1);
		USBReset = (ToggleButton) findViewById(R.id.USBReset);
		setupAccessory();

	}
 
	@Override
	public Object onRetainNonConfigurationInstance() {
		if (mAccessory != null) {
			return mAccessory;
		} else {
			return super.onRetainNonConfigurationInstance();
		}
	}
 
	@Override
	public void onResume() {
		super.onResume();
 
		if (mInputStream != null && mOutputStream != null) {
			//streams were not null");
			return;
		}
		//streams were null");
		UsbAccessory[] accessories = mUsbManager.getAccessoryList();
		UsbAccessory accessory = (accessories == null ? null : accessories[0]);
		if (accessory != null) {
			if (mUsbManager.hasPermission(accessory)) {
				openAccessory(accessory);
			} else {
				synchronized (mUsbReceiver) {
					if (!mPermissionRequestPending) {
						mUsbManager.requestPermission(accessory, mPermissionIntent);
						mPermissionRequestPending = true;
					}
				}
			}
		} else {
			// null accessory
		}
	}
 
	@Override
	public void onPause() {
		super.onPause();
	}
 
	@Override
	public void onDestroy() {
		unregisterReceiver(mUsbReceiver);
		super.onDestroy();
	}
 
	Handler mHandler = new Handler() {
		@Override
		public void handleMessage(Message msg) {
			ValueMsg t = (ValueMsg) msg.obj;

			if (t.getFlag() == 'A'){
				readIn1 = t.getReading();
				messagedata.dataplayer1 = readIn1;
			}
			if (t.getFlag() == 'B'){
				readIn2 = t.getReading();
				messagedata.dataplayer2 = readIn2;
			}
			if (t.getFlag() == 'C'){
				readIn3 = t.getReading();
				messagedata.outputPWM1 = readIn3;
			}
			if (t.getFlag() == 'D'){
				readIn4 = t.getReading();
				messagedata.outputPWM2 = readIn4;
			}
				

			// this is where you handle the data you sent. You get it by calling the getReading() function
//			 mResponseField.setText("Flag: "+t.getFlag()+"; Reading: "+t.getReading()+"; Date: "+(new Date().toString()));
			mResponseField.setText("Reading1:" + readIn1 + "     Reading2:" + readIn2);
			
		}
		
	};
 
	private void setupAccessory() {
		mUsbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
		mPermissionIntent =PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
		IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
		filter.addAction(UsbManager.ACTION_USB_ACCESSORY_DETACHED);
		registerReceiver(mUsbReceiver, filter);
		if (getLastNonConfigurationInstance() != null) {
			mAccessory = (UsbAccessory) getLastNonConfigurationInstance();
			openAccessory(mAccessory);
		}
	}
 
	private void openAccessory(UsbAccessory accessory) {
		mFileDescriptor = mUsbManager.openAccessory(accessory);
		if (mFileDescriptor != null) {
			mAccessory = accessory;
			FileDescriptor fd = mFileDescriptor.getFileDescriptor();
			mInputStream = new FileInputStream(fd);
			mOutputStream = new FileOutputStream(fd);
			Thread thread = new Thread(null, this, "OpenAccessoryTest");
			thread.start();
			//Accessory opened
		} else {
			// failed to open accessory
		}
	}
 
	private void closeAccessory() {
		try {
			if (mFileDescriptor != null) {
				mFileDescriptor.close();
			}
		} 
		catch (IOException e) {
		} 
		finally {
			mFileDescriptor = null;
			mAccessory = null;
		}
	}
	
	public void run() { 
		int ret = 0;
		byte[] buffer = new byte[16384];
		int i;
		int [] valueSensor = new int[10]; // support for up to 10 sensors
		 
		while (true) { //Receive Data
			sendData();
			try {
				ret = mInputStream.read(buffer); //Read the stream and put into buffer, returns number of bytes into ret
			} catch (IOException e) {
				break;
			}

			i = 0;
			
			while (i < ret) { //step through the bytes in buffer
				int len = ret - i;
				if (len >= 1) {
					Message m = Message.obtain(mHandler);
					Message n = Message.obtain(mHandler);
					Message m2 = Message.obtain(mHandler);
					Message n2 = Message.obtain(mHandler);
					//Looking for messages of the type "0xxxx" where xx is the data from sensor 1 then 2 followed by pwm output value from 1 to 2
					//Below follows along with the input matching with the protocol
					if( (int)buffer[i] == 0){
						i++;
						valueSensor[0] = (int)buffer[i];
						i++;
						valueSensor[1] = (int)buffer[i];
						i++;
						valueSensor[2] = (int)buffer[i];
						i++;
						valueSensor[3] = (int)buffer[i];
						i++;
					}

					// 'f' is the flag, use for your own logic
					// value is the value from the arduino
					m.obj = new ValueMsg('A', valueSensor[0]);
					mHandler.sendMessage(m);

					n.obj = new ValueMsg('B', valueSensor[1]);
					mHandler.sendMessage(n);
					
					m2.obj = new ValueMsg('C', valueSensor[2]);
					mHandler.sendMessage(m2);

					n2.obj = new ValueMsg('D', valueSensor[3]);
					mHandler.sendMessage(n2);
				}
			}
		}
	}
	
	public static byte[] toByta(float data) {
		//convert a float to a byte array of size 4
	    return toByta(Float.floatToRawIntBits(data));
	}
	
	public static byte[] toByta(int data) {
		//convert an int to a byte array of size 4
	    return new byte[] {
	        (byte)((data >> 24) & 0xff),
	        (byte)((data >> 16) & 0xff),
	        (byte)((data >> 8) & 0xff),
	        (byte)((data >> 0) & 0xff),
	    };
	}
	
	public void sendData(){
		byte[] bufferLED = new byte[3]; //Following comm protocol: 0, X, X, int top, int bottom  ~~ each int is 4 bytes (32 bit) between 0 and 10,000
		byte[] bufferTopBox = toByta(messagedata.topBoxSetpoint);
		byte[] bufferBottomBox = toByta(messagedata.bottomBoxSetpoint);
		
		byte[] test = {0x00, 0x00, 0x00, 0x0a};
		//Fill with test array
		//bufferTopBox = test;
		//bufferBottomBox = test;
		
		bufferLED[0] = 0;
		if (messagedata.userInTopBox == 1){
			bufferLED[1]=(byte)1;
		}
		else{
			bufferLED[1]=(byte)0;
		}
		
		if (messagedata.userInBottomBox == 1){
			bufferLED[2]=(byte)1;
		}
		else{
			bufferLED[2]=(byte)0;
		}
		
		//combine the arrays
		byte[] buffer = new byte[11]; // 3 + 4 + 4
		for(int i = 0; i < 11; i++){
			if (i<3){
				buffer[i] = bufferLED[i];
			}
			if (i >= 3 && i<7){
				buffer[i] = bufferTopBox[i-3];
			}
			if (i >= 7 && i<11){
				buffer[i] = bufferBottomBox[i-7];
			}
		}

		if (mOutputStream != null) {

			try {
				mOutputStream.write(buffer);
				
			} catch (IOException e) {
				Log.e(TAG, "write failed", e);
			}
		}
	}
	// goes to Arduino
	public void blinkLED(){
		//do nothing if blinkLED button in xml is pushed
	}
	
	public void USBReset(View v){
		closeAccessory();
		setupAccessory();
//		mAccessory = (UsbAccessory) getLastNonConfigurationInstance();
//		openAccessory(mAccessory);
	}

	private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
		@Override
		public void onReceive(Context context, Intent intent) {
			String action = intent.getAction();
			if (ACTION_USB_PERMISSION.equals(action)) {
				synchronized (this) {
					UsbAccessory accessory = (UsbAccessory) intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY); // Changed for tablet support (hopefully)
					if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
						openAccessory(accessory);
					} else {
						// USB permission denied
					}
				}
			} else if (UsbManager.ACTION_USB_ACCESSORY_DETACHED.equals(action)) {
				UsbAccessory accessory = (UsbAccessory) intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY); // Changed for tablet support (hopefully)
				if (accessory != null && accessory.equals(mAccessory)) {
					//accessory detached
					closeAccessory();
				}
			}
		}
	};
}